package com.lzh.hosp.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzh.hosp.exception.ScheduleException;
import com.lzh.hosp.model.Doctor;
import com.lzh.hosp.model.ResponseResult;
import com.lzh.hosp.model.ResultCodeEnum;
import com.lzh.hosp.model.Schedule;
import com.lzh.hosp.model.dto.ScheduleQueryDto;
import com.lzh.hosp.service.*;
import com.lzh.hosp.mapper.ScheduleMapper;
import com.lzh.hosp.utils.DateUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
* @author 59399
* @description 针对表【schedule(医生日程安排表)】的数据库操作Service实现
* @createDate 2023-03-16 20:59:24
*/
@Service
public class ScheduleServiceImpl extends ServiceImpl<ScheduleMapper, Schedule>
    implements ScheduleService{

    @Autowired
    private DictService dictService;

    @Autowired
    private DoctorService doctorService;

    @Autowired
    private PrescriptionService prescriptionService;

    @Autowired
    private CommentService commentService;

    @Override
    public List<Schedule> get(ScheduleQueryDto scheduleQueryDto) {
        QueryWrapper<Schedule> wrapper = new QueryWrapper<>();
        //如果scheduleQueryVo不为空，获取里面的值
        if (!StringUtils.isEmpty(scheduleQueryDto)){
            Long depcode = scheduleQueryDto.getDepcode();
            String docname = scheduleQueryDto.getDocname();
            Long docId = scheduleQueryDto.getDocId();
            String workDate = scheduleQueryDto.getWorkDate();
            Integer workTime[] = scheduleQueryDto.getWorkTime();

            wrapper.like(!StringUtils.isEmpty(docname),"docname",docname);
            wrapper.eq(!StringUtils.isEmpty(depcode),"depcode",depcode);
            wrapper.eq(!StringUtils.isEmpty(docId),"doc_id",docId);
            wrapper.eq(!StringUtils.isEmpty(workDate),"work_date",workDate);
            wrapper.in(!StringUtils.isEmpty(workTime),"work_time",workTime);
        }
        List<Schedule> scheduleList = baseMapper.selectList(wrapper);
        for (Schedule schedule : scheduleList) {
            Map<String,Object> params = new HashMap<>();
            //设置工作信息
            String dateStr = new DateTime(schedule.getWorkDate()).toString("MM-dd");
            params.put("workDate",dateStr);
            params.put("workTime",workTime(schedule.getWorkTime()));
            params.put("dayOfWeek",dayOfWeekCn(new DateTime(schedule.getWorkDate()).getDayOfWeek()));
            //设置科室、医生信息
            String depname = dictService.getDictName(Long.valueOf(schedule.getDepcode()));
            Doctor doctor = doctorService.getById(schedule.getDocId());
            String docname = doctor.getUsername();
            String professionalTitle = doctor.getProfessionalTitle();
            params.put("depname",depname);
            params.put("docname",docname);
            params.put("professionalTitle",professionalTitle);
            schedule.setParams(params);
        }
        return scheduleList;
    }

    @Override
    @Transactional
    public void batchAdd(List<Schedule> list) {
        for(int i=0;i<list.size();i++){
            boolean flag = this.add(list.get(i));
            if (!flag){
                //抛出异常
                int line = i+2;
                throw new RuntimeException("第"+line+"行格式错误");
            }
        }
    }

    @Override
    public boolean add(Schedule schedule) {
        //查询排班日期是否是今天或者是昨天的或者是14天之后的
        //查询医生的认证状态
        Long docId = schedule.getDocId();
        Doctor doctor = doctorService.getById(docId);
        Integer authStatus = doctor.getAuthStatus();
        if (authStatus!=1){//说明没有认证
            throw new ScheduleException("医生未进行认证", ResultCodeEnum.FAIL.getCode());
        }
        //查询医生是否在该时间段进行了排班
        Integer workTime = schedule.getWorkTime();
        Date workDate = schedule.getWorkDate();
        QueryWrapper<Schedule> wrapper = new QueryWrapper<>();
        wrapper.eq("doc_id",docId);
        wrapper.eq("work_time",workTime);
        wrapper.eq("work_date",new DateTime(workDate).toString("yyyy-MM-dd"));
        Schedule sche = baseMapper.selectOne(wrapper);
        if (!StringUtils.isEmpty(sche)){//说明医生已经在该时间段进行了排班
            throw new ScheduleException("医生已在该时间段进行排班", ResultCodeEnum.FAIL.getCode());
        }
        if (!DateUtils.isEffectiveDay(workDate)){//说明排班日期不在范围内（14天以内）
            throw new ScheduleException("排版日期不在范围内（14内）", ResultCodeEnum.FAIL.getCode());
        }
        schedule.setAvailableNumber(schedule.getReservedNumber());
        schedule.setStatus(1);
        baseMapper.insert(schedule);
        return true;
    }

    @Override
    public List<Doctor> findRecently(Long depcode) {
        //计算出最近14天的日期
        List<String> list = new ArrayList<>();
        DateTime dateTime = new DateTime();
        for (int i=0;i<14;i++){
            DateTime date = dateTime.plusDays(i);
            list.add(date.toString("yyyy-MM-dd"));
        }

        //根据日期查出排班
        QueryWrapper<Schedule> wrapper = new QueryWrapper<>();
        wrapper.in("work_date",list);
        wrapper.eq("depcode",depcode);
        List<Schedule> scheduleList = baseMapper.selectList(wrapper);
        if (scheduleList.size()==0){
            return null;
        }

        //取出scheduleList中的医生id
        Set<Long> docIdList = new HashSet<>();
        for (Schedule schedule : scheduleList) {
            docIdList.add(schedule.getDocId());
        }

        //往每个元素设置额外信息
        List<Doctor> doctorList = doctorService.listByIds(docIdList);
        for (Doctor doctor : doctorList) {
            Map<String,Object> params = new HashMap<>();
            //接诊数量
            int numberOfVisitsReceived = prescriptionService.getNumberOfVisitsReceived(doctor.getId());
            params.put("numberOfVisitsReceived",numberOfVisitsReceived);

            //好评数量
            Integer numberOfPositiveComment = commentService.getNumberOfPositiveComment(doctor.getId());
            params.put("numberOfPositiveComment",numberOfPositiveComment);

            doctor.setParams(params);
        }
        return doctorList;
    }

    @Override
    public List<Doctor> findByDepcodeAndWorkDate(ScheduleQueryDto scheduleQueryDto) {
        //todo 可以用sql语句处理，减少代码量
        //根据日期查出排班
        QueryWrapper<Schedule> wrapper = new QueryWrapper<>();
        wrapper.eq("work_date", scheduleQueryDto.getWorkDate());
        wrapper.eq("depcode", scheduleQueryDto.getDepcode());
        List<Schedule> scheduleList = baseMapper.selectList(wrapper);
        if (scheduleList.size()==0){
            return null;
        }

        //取出scheduleList中的医生id
        Set<Long> docIdList = new HashSet<>();
        for (Schedule schedule : scheduleList) {
            docIdList.add(schedule.getDocId());
        }

        //往每个元素设置额外信息
        List<Doctor> doctorList = doctorService.listByIds(docIdList);
        for (Doctor doctor : doctorList) {
            Map<String,Object> params = new HashMap<>();
            //设置科室编号
            String depname = dictService.getDictName(doctor.getDepcode());
            params.put("depname",depname);
            //接诊数量
            int numberOfVisitsReceived = prescriptionService.getNumberOfVisitsReceived(doctor.getId());
            params.put("numberOfVisitsReceived",numberOfVisitsReceived);

            //好评数量
            Integer numberOfPositiveComment = commentService.getNumberOfPositiveComment(doctor.getId());
            params.put("numberOfPositiveComment",numberOfPositiveComment);
            doctor.setParams(params);
        }
        return doctorList;
    }

    @Override
    public List<Schedule> findByDocId(Long docId) {
        QueryWrapper<Schedule> wrapper = new QueryWrapper<>();
        wrapper.eq("doc_id",docId);
        wrapper.ge("work_date",new DateTime(new Date()).toString("yyyy-MM-dd"));
        //构造不符合条件的排班信息（超过排班时间）
        List<Integer> workTimeList = DateUtils.computeTime();
        if (workTimeList.size()>0){
            String dts = new DateTime(new Date()).toString("yyyy-MM-dd");
            List<Long> idList = this.baseMapper.selectIllegal(dts, workTimeList);
            wrapper.notIn(idList.size()>0,"id",idList);
        }
        List<Schedule> scheduleList = baseMapper.selectList(wrapper);
        for (Schedule schedule : scheduleList) {
            Map<String,Object> params = new HashMap<>();
            String dateStr = new DateTime(schedule.getWorkDate()).toString("MM-dd");
            params.put("workDate",dateStr);
            params.put("workTime",workTime(schedule.getWorkTime()));
            params.put("dayOfWeek",dayOfWeekCn(new DateTime(schedule.getWorkDate()).getDayOfWeek()));
            schedule.setParams(params);
        }
        return scheduleList;
    }

    @Override
    public List<Long> getDocIdByDepCodeAndDate(String date, Long docId) {
        return baseMapper.selectDocIdByDepCodeAndDate(date,docId);
    }

    @Override
    public List<JSONObject> getRecentDayByDocId(Long docId) {
        //获取近14天的日期
        List<String> day = get14Day();

        //构造查询条件
        QueryWrapper<Schedule> wrapper = new QueryWrapper<>();
        wrapper.eq("doc_id",docId);
        wrapper.in("work_date",day);

        List<Schedule> scheduleList = baseMapper.selectList(wrapper);
//        Set<Date> dayList = scheduleList.stream().map(Schedule::getWorkDate).collect(Collectors.toSet());
        Set<Date> dayList = new TreeSet<>();
        for (Schedule schedule : scheduleList) {
            dayList.add(schedule.getWorkDate());
        }
        List<JSONObject> dayJsonList = new ArrayList<>();
        for (Date date : dayList) {
            DateTime dateTime = new DateTime(date);
            JSONObject json = new JSONObject();
            json.put("key",dateTime.toString("yyyy-MM-dd"));
            json.put("value",dateTime.toString("MM-dd"));
            dayJsonList.add(json);
        }
        return dayJsonList;
    }

    @Override
    public List<String> get14Day() {
        List<String> list = new ArrayList<>();
        DateTime dateTime = new DateTime();
        for (int i=0;i<14;i++){
            DateTime date = dateTime.plusDays(i);
            list.add(date.toString("yyyy-MM-dd"));
        }
        return list;
    }

    private static String workTime(int time){
        switch (time){
            case 1:
                return "8:30-10:30";
            case 2:
                return "10:30-11:30";
            case 3:
                return "14:30-15:30";
            case 4:
                return "15:30-17:30";
            default:
                return "";
        }
    }

    private static String dayOfWeekCn(int day){
        switch (day){
            case 1:
                return "一";
            case 2:
                return "二";
            case 3:
                return "三";
            case 4:
                return "四";
            case 5:
                return "五";
            case 6:
                return "六";
            case 7:
                return "日";
            default:
                return "";
        }
    }
}




